package com.rivues.util.tools;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;

import com.itextpdf.awt.geom.Line2D.Float;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.AnalyzerReport;
import com.rivues.module.platform.web.model.AnalyzerReportModel;
import com.rivues.module.platform.web.model.JobDetail;
import com.rivues.module.platform.web.model.ReportFilter;
import com.rivues.util.RivuTools;
import com.rivues.util.data.CubeData;
import com.rivues.util.data.FirstTitle;
import com.rivues.util.data.Level;
import com.rivues.util.data.ReportData;
import com.rivues.util.data.ValueData;



/**
 * 导出PDF
 * @author Jason Chen
 *
 */
public class RivuPDFUtil implements ExportFile{
	
	private ReportData reportData;
	private AnalyzerReportModel model;
	private AnalyzerReport report ;
	
	public static final Boolean IS_LOCAL_DATAFILE= true;
	
	private int cellNumber = 0;		//总列数
	
	private int rowTitleNum =0;
	
	private Document dom ;	
	
	private int rowNum = 0;
	
	private Font fontChineseHead;
	
	private Font fontChineseContent;
	
	private Font fontChineseTitle;
	
	private Font fontChinesFirstTitle;
	
	private PdfPTable table;
	
	private JobDetail job;
	
	private String startTime ="";
	
	private String endTime = "";
	
	private String headTitle ="报表";
	
	private OutputStream out ;
	
	int  page = 1 ;
	
	public RivuPDFUtil(AnalyzerReportModel model,AnalyzerReport report, OutputStream out){
		this.model = model;
		this.report = report;
		this.out = out ;
		this.createFontChinese();
		dom= new Document(PageSize.A1.rotate());
		if(!StringUtils.isBlank(report.getReportname())){
			this.headTitle = report.getReportname();
		}
		try {
			PdfWriter.getInstance(dom, out);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		dom.open();			//打开文档
	}
	
	/**
	 * 创建PDF
	 * @param fileName
	 */
	public void createFile(boolean limit) throws Exception {
		try {
			cellNumber = reportData.getCol().getChilderen().size() + (reportData.getRow()!=null && reportData.getRow().getFirstTitle()!=null ? reportData.getRow().getFirstTitle().size(): 0) ;	//总列数	
			this.createTable();
			this.createHeadCell();
			this.createSubHeadCell();
			this.createTitleCell();
			this.createContentCell();
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
	}
	
	/**
	 * 定义中文字
	 */
	protected void createFontChinese(){
		BaseFont bfChinese;
		try {
			bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
			fontChineseHead = new Font(bfChinese, 35, Font.BOLD);
			fontChineseTitle = new Font(bfChinese, 30, Font.BOLD);
			fontChineseContent = new Font(bfChinese, 25, Font.NORMAL);
			fontChinesFirstTitle = new Font(bfChinese, 25, Font.BOLD);
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 * 定义表
	 * @throws BadElementException 
	 */
	protected void createTable() throws BadElementException{
		cellNumber = reportData.getCol().getChilderen().size() + (reportData.getRow()!=null && reportData.getRow().getFirstTitle()!=null ? reportData.getRow().getFirstTitle().size(): 0) ;	//总列数
		table = new PdfPTable(cellNumber);
		table.setHorizontalAlignment(Element.ALIGN_LEFT);
		table.setSpacingAfter(5);
		table.setSpacingBefore(5);
		//设置页面总宽度。
				if(cellNumber>=10){
					table.setTotalWidth(2200);
				}else if(cellNumber>6&&cellNumber<10){
					table.setTotalWidth(1000);
				}else if(cellNumber<=6){
					table.setTotalWidth(500);
				}
		float [] widths = new float[cellNumber];
		widths[0] = (float)600;
		for(int i=1;i<cellNumber;i++){
			widths[i] = (float)(1600/cellNumber-1);
		}
		
		table.setLockedWidth(true);
		
	}
	
	/**
	 * 定义头部
	 */
	protected void createHeadCell(){
		PdfPCell cellHead = this.createBaseCellStyle(new Paragraph(headTitle, fontChineseHead));
		cellHead.setColspan(cellNumber);
		cellHead.setFixedHeight(50);
		table.addCell(cellHead);	
	}
	
	/**
	 * 定义副标题
	 */
	protected void createSubHeadCell(){
		StringBuffer strb = new StringBuffer();
		if(this.model.getFilters()!=null && this.model.getFilters().size()>0){
			for(ReportFilter filter : this.model.getFilters()){
				if(!filter.isChild()){
					if(!RivuDataContext.ReportCompareEnum.COMPARE.toString().equals(filter.getValuefiltertype())){
						if(StringUtils.isBlank(filter.getCurvalue())){
							strb.append(filter.getName()).append(":").append(RivuTools.getDefaultValue(filter , RivuDataContext.ReportCompareEnum.COMPARE.toString() , null)).append("                      ") ;
						}
					}else{
						if(!StringUtils.isBlank(filter.getCurstartvalue())&&!StringUtils.isBlank(filter.getCurendvalue())){
							strb.append(filter.getName()).append(":").append(RivuTools.getDefaultValue(filter , RivuDataContext.ReportCompareEnum.START.toString() , null)).append(" ~ ").append(RivuTools.getDefaultValue(filter , RivuDataContext.ReportCompareEnum.END.toString() , null)).append("                      ") ;
						}
					}
					
				}
			}
		}else{
			strb.append("报表生成日期:").append(getNowDate()) ;
		}
		PdfPCell subHeadCell = this.createBaseCellStyle(new Paragraph(strb.toString(), fontChineseContent));
		subHeadCell.setColspan(cellNumber);
		subHeadCell.setFixedHeight(40);
		subHeadCell.setHorizontalAlignment(Element.ALIGN_LEFT);
		table.addCell(subHeadCell);
	}
	
	/**
	 * 定义标题列
	 * @throws BadElementException
	 */
	protected void createTitleCell(){
		
		if(reportData.getRow() != null && reportData.getRow().getFirstTitle()!=null){
			for(FirstTitle firstTitle:reportData.getRow().getFirstTitle()){
				table.addCell(createTitleCellStyle(new Paragraph(firstTitle.getName(), fontChinesFirstTitle)));	
			}
		}
		List<List<Level>> title = reportData.getCol().getTitle();
		if(title!=null){
			for(List<Level> levelList : title){
				for(Level level : levelList){
					table.addCell(createTitleCellStyle(new Paragraph(level.getName(), fontChinesFirstTitle)));	
				}
			}
		}
	}
	
	/**
	 * 定义表格内容
	 * @throws BadElementException
	 */
	protected void createContentCell(){
		

		PdfPCell contentcell = null;
		if(reportData.getRow()!=null){
			List<List<Level>> rowlst = reportData.getRow().getTitle();
			List<List<ValueData>> dataList = reportData.getData();
			
			for(int r =0;dataList!=null && r<dataList.size();r++){
				
				//weidu
				for(int c = 0;c<rowlst.size();c++){
					int rowspan = 0 ;
					List<Level> leveList = rowlst.get(c) ;
					Level currentLevel = null ;
					for(Level level : leveList){
						if(rowspan == r){
							currentLevel = level ;
							break ;
						}
						rowspan = rowspan + (level.getRowspan()>0 ? level.getRowspan() : 1 );
						
					}
					if(currentLevel!=null){
						String value = String.valueOf(currentLevel.getName());
						
						contentcell = this.createTitleCellStyle(new Paragraph(value, fontChineseContent));
						contentcell.setFixedHeight(40);
						if(currentLevel!=null && currentLevel.getRowspan()>1){
							contentcell.setRowspan(currentLevel.getRowspan());
						}else if(currentLevel!=null && currentLevel.getColspan()>1){
							contentcell.setColspan(currentLevel.getColspan());
						}
						table.addCell(contentcell);
					}
				}
				//zhibiao
				for(int j = 0;j<dataList.get(r).size();j++){
					String value = String.valueOf(dataList.get(r).get(j));
					
					if(!"".equals(value)){
						contentcell = this.createBaseCellStyle(new Paragraph(com.itextpdf.awt.geom.Rectangle2D.Float.OUT_LEFT ,value, fontChineseContent));
					}else{
						contentcell = this.createBaseCellStyle(new Paragraph(com.itextpdf.awt.geom.Rectangle2D.Float.OUT_LEFT ,"", fontChineseContent));
					}
					
					if(dataList.get(r).get(j)!=null && dataList.get(r).get(j).getRowspan()>1){
						contentcell.setRowspan(dataList.get(r).get(j).getRowspan());
					}else if(dataList.get(r).get(j)!=null && dataList.get(r).get(j).getColspan()>1){
						contentcell.setColspan(dataList.get(r).get(j).getColspan());
					}
					contentcell.setFixedHeight(40);
					table.addCell(contentcell);
				}
			
				
				rowNum++;
			}
			
		}else{
			
			CubeData cdata=(CubeData)reportData;
			List<List<ValueData>> dataList = reportData.getData();
			for(int r =0;cdata.getItem()!=null && r<cdata.getItem().size();r++){
				
				for(int c =1;r<dataList.size() && c<dataList.get(r).size()+1;c++){
					contentcell = this.createBaseCellStyle(new Paragraph(com.itextpdf.awt.geom.Rectangle2D.Float.OUT_LEFT ,String.valueOf(dataList.get(r).get(c-1)), fontChineseContent));
					contentcell.setFixedHeight(40);
					table.addCell(contentcell);
				}
				rowNum++;
			}
			
			
		}
	}
	
	private boolean checkIsNumber(String str){
		Pattern p = Pattern.compile("^(-?\\d+)(\\.\\d+)?$");
		Matcher m = p.matcher(str);
		return m.matches();
	}
	
	protected PdfPCell createBaseCellStyle(Paragraph pg){

		PdfPCell cell = new PdfPCell(pg);
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		
		return cell;
	}
	
	
	protected PdfPCell createContentCellStyle(Paragraph pg){
		PdfPCell cell = createBaseCellStyle(pg);
		cell.setFixedHeight(35);
		return cell;
	}
	
	protected PdfPCell createTitleCellStyle(Paragraph pg){
		PdfPCell cell = createContentCellStyle(pg);
		cell.setFixedHeight(35);
		cell.setBackgroundColor(new BaseColor(204,255,204));
		return cell;
	}
	
	
	/**
	 * 读本地测试数据文件
	 * @param path
	 * @return
	 */
	protected String readStr(String path){
		File file = new File(path);
		Reader reader = null;
		StringBuffer sf = new StringBuffer();
		try {
			reader = new InputStreamReader(new FileInputStream(file));
			 int tempchar;
	            while ((tempchar = reader.read()) != -1) {
	                
	                if (((char) tempchar) != '\r') {
	                    sf.append((char) tempchar);
	                }
	            }
	            reader.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return sf.toString();
	}
	
	private String getNowDate(){
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
		return sf.format(new Date());
	}
	
	
	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}

	public void setEndTime(String endTime) {
		this.endTime = endTime;
	}

	public void setHeadTitle(String headTitle) {
		this.headTitle = headTitle;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ObjectInputStream in;
		String fileName = "e:\\test\\mytest.pdf";
		try {
			in = new ObjectInputStream (new FileInputStream("E:\\test\\ttt.obj"));
			ReportData obj = (ReportData) in.readObject(); 
			
			System.out.println("obj=" + obj); 
			System.out.println(obj.getCol().getChilderen().size());
			in.close(); 
//			RivuPDFUtil excel = new RivuPDFUtil(obj);
//			excel.createFile(new FileOutputStream(fileName));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public String getHeadTitle() {
		// TODO Auto-generated method stub
		return this.headTitle;
	}

	@Override
	public String getStartTime() {
		// TODO Auto-generated method stub
		return this.startTime;
	}

	@Override
	public String getEndTime() {
		// TODO Auto-generated method stub
		return this.endTime;
	}

	@Override
	public void createFile(String filename) throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void createSheet(String sheetName) throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setReportData(ReportData reportData) throws Exception {
		// TODO Auto-generated method stub
		this.reportData = reportData;
	}

	@Override
	public void setModel(AnalyzerReportModel model) throws Exception {
		// TODO Auto-generated method stub
		this.model = model;
	}

	@Override
	public void setReport(AnalyzerReport report) throws Exception {
		// TODO Auto-generated method stub
		this.report = report;
	}

	@Override
	public void setRowNum(int rowNum) throws Exception {
		// TODO Auto-generated method stub
		this.rowNum = rowNum;
	}

	@Override
	public int getRowNum() throws Exception {
		// TODO Auto-generated method stub
		return rowNum;
	}

	@Override
	public void close() {
		try {
			dom.add(table);
			dom.close();		//关闭文档
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void setPage(int page) throws Exception {
		// TODO Auto-generated method stub
		this.page=page;
	}

	@Override
	public void setOut(OutputStream out) throws Exception {
		// TODO Auto-generated method stub
		this.out = out;
	}

	@Override
	public int getPage() throws Exception {
		// TODO Auto-generated method stub
		return this.page;
	}

	@Override
	public void setJobDetail(JobDetail job) {
		// TODO Auto-generated method stub
		this.job = job;
	}

	@Override
	public JobDetail getJobDetail() {
		// TODO Auto-generated method stub
		return this.job;
	}

	@Override
	public void writeHead(ReportData reportData) throws Exception {
		// TODO Auto-generated method stub
		if(this.reportData == null){
			this.reportData = reportData ;
		}
		this.createTable();
		this.createHeadCell();
		this.createSubHeadCell();
		this.createTitleCell();
		
	}

	@Override
	public void writeRow(ReportData reportData) throws Exception {
		if(reportData!=null){
			this.reportData = reportData ;
			this.createContentCell();
		}
	}

	@Override
	public ReportData getReportData() {
		// TODO Auto-generated method stub
		return this.reportData;
	}

}
